using Admin.NET.Core;
using DocumentFormat.OpenXml.Office2013.Word;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MOKA.TPM.Application.Enum;

using MOKA.TPM.Application.Enum;

using MOKA.TPM.Entity;
using MOKA.TPM.Service.Dto;
using MOKA.TPM.Utility.Const;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.ComponentModel;
using System.Net;

namespace MOKA.TPM.Service;

/// <summary>
/// 生产设备服务
/// </summary>
[ApiDescriptionSettings(TPMConst.GroupName, Order = 860)]
public class Service_Equipment : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<Equipment> _rep;
    private readonly UserManager _userManager;
    private IHttpContextAccessor _accessor;//获取请求上下文_userRepository
    private readonly ISqlSugarClient _db;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="db"></param>
    /// <param name="rep"></param>
    /// <param name="userManager"></param>
    /// <param name="accessor"></param>
    public Service_Equipment(ISqlSugarClient db, SqlSugarRepository<Equipment> rep, UserManager userManager, IHttpContextAccessor accessor)
    {
        _db = db;
        _rep = rep;
        _userManager = userManager;
        _accessor = accessor;
    }

    /// <summary>
    /// 获取关联表
    /// </summary>
    /// <param name="querey"></param>
    /// <returns></returns>
    private ISugarQueryable<Equipment> GetIncludes(ISugarQueryable<Equipment> querey)
    {
        var querey1 = querey
            .Includes(a => a.sysDictDetail_CompanyCode)
            .Includes(a => a.sysDictDetail_TPMDeviceGroupId)
            .Includes(a => a.sysDictDetail_TPMCategoryId)
            .Includes(a => a.department_UserDepartmentID)
            .Includes(a => a.asset_AssetId)
            .Includes(a => a.sysDictDetail_EquipmentStatus)
            .Includes(a => a.sysDictDetail_Brand)
            .Includes(a => a.sysDictDetail_Supplier)
            .Includes(a => a.t__USER_Manager)
            .Includes(a => a.t__USER_UserNo)
            .Includes(a => a.t__USER_Checkuper)
            .Includes(a => a.t__USER_Upkeepr)
            .Includes(a => a.sysDictDetail_Position)
            //.IncludesAllSecondLayer(a => a.plcTypeBase_PLCType)
            .Includes(a => a.t__USER_CreateUser)
            .Includes(a => a.t__USER_UpdateUser)
            .Includes(a => a.Checkups); //详细表（无字典）
                                        //.Includes(a => a.EquipmentChanges) //详细表（无字典）
                                        //.Includes(a => a.EquipmentParases) //详细表（无字典）
                                        //.Includes(a => a.EquipmentPartses) //详细表（无字典）
                                        //.Includes(a => a.EquipmentPLCs) //详细表（无字典）
                                        //.Includes(a => a.EquipmentRepairs) //详细表（无字典）
                                        //.Includes(a => a.EquipmentSops) //详细表（无字典）
                                        //.Includes(a => a.UpkeepPlanEquipments) //详细表（无字典）            //.Includes(a => a.EquipmentChanges) //详细表（无字典）
                                        //.Includes(a => a.EquipmentParases) //详细表（无字典）
                                        //.Includes(a => a.EquipmentPartses) //详细表（无字典）
                                        //.Includes(a => a.EquipmentPLCs) //详细表（无字典）
                                        //.Includes(a => a.EquipmentRepairs) //详细表（无字典）
                                        //.Includes(a => a.EquipmentSops) //详细表（无字典）
                                        //.Includes(a => a.UpkeepPlanEquipments) //详细表（无字典）
        return querey1;
    }

    /// <summary>
    /// 获取Select
    /// </summary>
    /// <param name="querey"></param>
    /// <returns></returns>
    private ISugarQueryable<EquipmentOutput> GetSelect(ISugarQueryable<Equipment> querey)
    {
        var dto = querey.Select((a) => new EquipmentOutput()
        {
            Id = a.Id.SelectAll(),
            CompanyCodeNo = a.sysDictDetail_CompanyCode.ItemValue,//字典
            CompanyCodeName = a.sysDictDetail_CompanyCode.ItemName,//字典
            TPMDeviceGroupName = a.sysDictDetail_TPMDeviceGroupId.ItemName,//字典
            TPMCategory = a.sysDictDetail_TPMCategoryId.ItemValue,//字典
            TPMCategoryName = a.sysDictDetail_TPMCategoryId.ItemName,//字典
            UserDepartmentName = a.department_UserDepartmentID.DepartmentName,//字典
            EquipmentStatusName = a.sysDictDetail_EquipmentStatus.ItemName,//字典
            BrandName = a.sysDictDetail_Brand.ItemName,//字典
            SupplierName = a.sysDictDetail_Supplier.ItemName,//字典
            ManagerName = a.t__USER_Manager.UserRemark,//字典
            UserNoName = a.t__USER_UserNo.UserRemark,//字典
            CheckuperName = a.t__USER_Checkuper.UserRemark,//字典
            UpkeeprName = a.t__USER_Upkeepr.UserRemark,//字典
            PositionName = a.sysDictDetail_Position.ItemName,//字典
            AssetNo = a.asset_AssetId.AssetNo,
            AreaName = a.sysDictDetail_Position.sysDictDetail_ItemParent.ItemName,//字典
            CreateUserName = a.t__USER_CreateUser.UserRemark,//字典
            UpdateUserName = a.t__USER_UpdateUser.UserRemark,//字典
            asset_AssetId = a.asset_AssetId,
            // plcTypeBase_PLCType = a.plcTypeBase_PLCType,
            Checkups = a.Checkups, //详细表
            //EquipmentChanges = a.EquipmentChanges, //详细表
            //EquipmentParases = a.EquipmentParases, //详细表
            //EquipmentPartses = a.EquipmentPartses, //详细表
            //EquipmentPLCs = a.EquipmentPLCs, //详细表
            //EquipmentRepairs = a.EquipmentRepairs, //详细表
            //EquipmentSops = a.EquipmentSops, //详细表
            //UpkeepPlanEquipments = a.UpkeepPlanEquipments, //详细表
        });
        return dto;
    }

    /// <summary>
    /// 获取Mapper
    /// </summary>
    /// <param name="querey"></param>
    /// <returns></returns>
    private ISugarQueryable<EquipmentOutput> GetMapper(ISugarQueryable<EquipmentOutput> querey)
    {
        return querey.Mapper((item) =>
        {
            //Mapster映射转换，不能有SQL
            //TypeAdapterConfig config = new TypeAdapterConfig()
            //.ForType<ContractFile, ContractFileOutput>()
            //.IgnoreIf((src, dest) => src.File == null, "Id", "Name", "FileType", "FileName", "Suffix", "FilePath", "SizeKb", "Url")
            //    .Map(dest => dest.Id, src => src.File.Id)
            //    .Map(dest => dest.Name, src => src.File.Id + src.File.Suffix)
            //.Config
            //.ForType<JToken, JToken>()
            //    .MapWith(json => json)
            //.Config;
            //item.ContractBody = item.ContractBodyIn.Adapt<List<ContractFileOutput>>(config);
        });
    }

    /// <summary>
    /// 获取分页列表 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [DisplayName("获取分页列表")]
    public async Task<SqlSugarPagedList<EquipmentOutput>> Page(PageEquipmentInput input)
    {
        var querey = _rep.AsTenant().QueryableWithAttr<Equipment>();
        var quereyWithIncludes = GetIncludes(querey)
        //.LeftJoin<FlowStateinfo>((a, d) => a.Id == d.SourceId)
            .WhereIF(input.CompanyCode.HasValue, a => a.CompanyCode == input.CompanyCode)
            .WhereIF(!string.IsNullOrEmpty(input.EquipmentNo?.Trim()), a => a.EquipmentNo.Contains(input.EquipmentNo ?? "".Trim())) //唯一索引
            .WhereIF(!string.IsNullOrEmpty(input.Name?.Trim()), a => a.Name.Contains(input.Name ?? "".Trim()))
            .WhereIF(input.TPMCategoryId.HasValue, a => a.TPMCategoryId == input.TPMCategoryId)
            .WhereIF(input.Position.HasValue, a => a.Position == input.Position)
            .WhereIF(!string.IsNullOrEmpty(input.Manager?.Trim()), a => a.Manager.Contains(input.Manager ?? "".Trim()))
            .WhereIF(input.EquipmentStatus.HasValue, a => a.EquipmentStatus == input.EquipmentStatus)
            .WhereIF(input.Area.HasValue, a => a.sysDictDetail_Position.sysDictDetail_ItemParent.Id == input.Area)
            .Where(a => a.IsDelete == false)
       ;
        var quereyWithSelect = GetSelect(quereyWithIncludes);
        var lists = await GetMapper(quereyWithSelect)
            .OrderBuilder(input) //(input, "a.", "PartNo", false)
            .ToPagedListAsync(input.Page, input.PageSize);

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取列表🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取列表")]
    [AllowAnonymous]
    public async Task<List<EquipmentOutput>> GetList([FromQuery] GetEquipmentInput input)
    {
        var querey = _rep.AsTenant().QueryableWithAttr<Equipment>();
        var quereyWithIncludes = GetIncludes(querey)
            //.LeftJoin<FlowStateinfo>((a, d) => a.Id == d.SourceId)
            .WhereIF(input.CompanyCode.HasValue, a => a.CompanyCode == input.CompanyCode)
            .WhereIF(!string.IsNullOrEmpty(input.EquipmentNo?.Trim()), a => a.EquipmentNo.Contains(input.EquipmentNo ?? "".Trim())) //唯一索引
            .Where(a => a.IsDelete == false)
            .OrderByDescending(a => a.Id)
        ;
        var quereyWithSelect = GetSelect(quereyWithIncludes);
        var lists = await GetMapper(quereyWithSelect)
            .Take(20)//为了性能，只取20个。
            .ToListAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取单个对象(根据主键) 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "One")]
    [DisplayName("获取单个对象(根据主键)")]
    [AllowAnonymous]
    public async Task<EquipmentOutput> GetOne([FromQuery] EquipmentInput input)
    {
        var querey = _rep.AsTenant().QueryableWithAttr<Equipment>();
        var quereyWithIncludes = GetIncludes(querey)
        //.LeftJoin<FlowStateinfo>((a, d) => a.Id == d.SourceId)
            .WhereIF(input.Id.HasValue, a => a.Id == input.Id)
       ;
        var quereyWithSelect = GetSelect(quereyWithIncludes);
        var lists = await GetMapper(quereyWithSelect)
            .SingleAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 获取单个对象（根据唯一索引）🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "OneByUniq")]
    [DisplayName("获取单个对象(根据唯一索引)")]
    [AllowAnonymous]
    public async Task<EquipmentOutput> GetOneByUniq([FromQuery] Guid CompanyCode, [FromQuery] string EquipmentNo)
    {
        var querey = _rep.AsTenant().QueryableWithAttr<Equipment>();
        var quereyWithIncludes = GetIncludes(querey)
        //.LeftJoin<FlowStateinfo>((a, d) => a.Id == d.SourceId)
            .Where(a => a.CompanyCode == CompanyCode && a.EquipmentNo == EquipmentNo) //唯一索引
        ;
        var quereyWithSelect = GetSelect(quereyWithIncludes);
        var lists = await GetMapper(quereyWithSelect)
            .SingleAsync();

        //使用.ThenMapper继续查询有字典详细表
        return lists;
    }

    /// <summary>
    /// 添加 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    [DisplayName("添加")]
    [AllowAnonymous]
    public async Task<bool> AddData(AddEquipmentInput input)
    {
        var isExist = await _rep.IsAnyAsync(u => u.CompanyCode == input.CompanyCode && u.EquipmentNo == input.EquipmentNo); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "公司代码", input.CompanyCode + "设备编号", input.EquipmentNo);
        }

        var entity = input.Adapt<Equipment>(); //将AddEquipmentInput转成Equipment

        //entity.Code = "thisCode"; //后台生成字段值

        //启动事务
        using (var uow = _db.CreateContext())
        {
            var ret = await _rep.AsInsertable(entity).EnableDiffLogEvent().ExecuteReturnEntityAsync();//插入后返回实体

            //插入详细表
            foreach (var item in entity.Checkups)
            {
                item.EquipmentId = ret.Id;
            }
            SqlSugarRepository<Checkup> _repCheckup = _rep.ChangeRepository<SqlSugarRepository<Checkup>>();
            await _repCheckup.InsertRangeAsync(entity.Checkups);//批量插入

            //提交事务
            uow.Commit();
            return ret != null;
        }
    }

    /// <summary>
    /// 更新 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    [DisplayName("更新")]
    [AllowAnonymous]
    public async Task<bool> UpdateData(UpdateEquipmentInput input)
    {
        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        isExist = await _rep.IsAnyAsync(u => u.CompanyCode == input.CompanyCode && u.EquipmentNo == input.EquipmentNo && u.Id != input.Id); //唯一索引是否存在
        if (isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "公司代码", input.CompanyCode + "设备编号", input.EquipmentNo);
        }
        var entity = input.Adapt<Equipment>(); //将UpdateEquipmentInput转成Equipment

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).IgnoreNullColumns().EnableDiffLogEvent().ExecuteCommandAsync() > 0;

            //更新详细表
            foreach (var item in entity.Checkups)
            {
                item.EquipmentId = entity.Id;
            }
            SqlSugarRepository<Checkup> _repCheckup = _rep.ChangeRepository<SqlSugarRepository<Checkup>>();
            await _repCheckup.AsDeleteable().Where(it => it.EquipmentId == entity.Id).ExecuteCommandAsync();//全删除
            await _repCheckup.InsertRangeAsync(entity.Checkups);//批量插入

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 删除 🧩
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
    [DisplayName("删除")]
    [AllowAnonymous]
    public async Task<bool> DeleteData(DeleteEquipmentInput input)
    {
        var entity = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);

        //启动事务
        using (var uow = _db.CreateContext())
        {
            //真正删除详细表
            SqlSugarRepository<Checkup> _repCheckup = _rep.ChangeRepository<SqlSugarRepository<Checkup>>();
            await _repCheckup.AsDeleteable().Where(it => it.EquipmentId == entity.Id).ExecuteCommandAsync();//全删除
            bool ret = await _rep.Context.Deleteable(entity).EnableDiffLogEvent().ExecuteCommandAsync() > 0;

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    /// <summary>
    /// 修改部分数据 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateSome"), HttpPost]
    [DisplayName("修改部分数据")]
    [AllowAnonymous]
    public async Task<bool> UpdateSomeData(UpdateSomeEquipmentInput input)
    {
        var request = _accessor.HttpContext.Request;
        // 你可以在这里使用 request 对象
        string ClientToken = WebUtility.UrlDecode(request.Headers["token"].ToString());
        UserToken TokenCs = JsonConvert.DeserializeObject<UserToken>(ClientToken);
        if (TokenCs == null)
        {
            throw new Exception("Token为空");
        }
        string UserAccount = TokenCs.UserAccount;

        //主键是否存在
        var isExist = await _rep.IsAnyAsync(u => u.Id == input.Id);
        if (!isExist)
        {
            throw Oops.Oh(TpmErrorCodeEnum.FieldValueNotExist, "Id", input.Id);
        }

        if (input.ToUpdateFields.Count() == 0)
        {
            throw new Exception("没有传入更新的字段");
        }
        input.UpdateUser = UserAccount;
        input.UpdateTime = DateTime.Now;
        input.ToUpdateFields.AddRange(new List<string>() { "updateUser", "updateTime" });
        var entity = input.Adapt<Equipment>(); //将UpdateEquipmentInput转成Equipment

        for (int index = 0; index < input.ToUpdateFields.Count(); index++)
        {
            var filed = input.ToUpdateFields[index];
            input.ToUpdateFields[index] = CapitalizeFirstLetter(filed);
        }

        //启动事务
        using (var uow = _db.CreateContext())
        {
            bool ret = await _rep.AsUpdateable(entity).UpdateColumns(input.ToUpdateFields.ToArray(), true).ExecuteCommandAsync() > 0;

            if (ret == false)
            {
                throw new Exception("更新行数为0");
            }

            //插入修改历史表
            //有空再做

            //提交事务
            uow.Commit();
            return ret;
        }
    }

    public static string CapitalizeFirstLetter(string input)
    {
        if (string.IsNullOrEmpty(input))
            return input;

        return char.ToUpper(input[0]) + input.Substring(1).ToLower();
    }

    /// <summary>
    /// 批量添加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "AddRange"), HttpPost]
    [DisplayName("批量添加")]
    [AllowAnonymous]
    public async Task<int> AddBulkData(List<Equipment> input)
    {
        foreach (var item in input)
        {
            var isExist = await _rep.IsAnyAsync(u => u.CompanyCode == item.CompanyCode && u.EquipmentNo == item.EquipmentNo); //唯一索引是否存在
            if (isExist)
            {
                throw Oops.Oh(TpmErrorCodeEnum.FieldValueExisted, "公司代码", item.CompanyCode + "设备编号", item.EquipmentNo);
            }
        }

        //启动事务
        using (var uow = _db.CreateContext())
        {
            int ret = await _rep.Context.Insertable(input).ExecuteCommandAsync();
            //不需要上传详细表了

            //提交事务
            uow.Commit();
            return ret;
        }
    }
}